#include "plane.h"
#include "gameview.h"

#include <QPainter>
#include <QDebug>
#include <utility>
Bullet::Bullet(const QPixmap &pixmap, int damage, qreal speed, GameView *view) : GamePixmapItem(pixmap, view), _damage(damage) {
    GameItem::setSpeed(QPointF(0, speed));
    type = "bullet";
}
int Bullet::damage() const {
    return _damage;
}
Bullet::Bullet(const BulletInfo &info) : Bullet(info.pixmap, info.damage, info.speed) {}

Plane::Plane(const QPixmap &pixmap, GameView *view) : GamePixmapItem(pixmap, view){}
Plane::Plane(const PlaneInfo &info, GameView *view)
    : GamePixmapItem(info.pixmap, view), hp(info.hp), max_speed(info.speed){}
void Plane::changeHp(int diff_amount) {
    hp += diff_amount;
    emit hpChanged(hp, diff_amount);
    if(hp <= 0){
        emit destroyed(this);
    }
}
void Plane::damage(int amount) {
    changeHp(-amount);
}
void Plane::heal(int amount) {
    changeHp(amount);
}

QList<Bullet *> Plane::GenerateBullet() {
    QList<Bullet *> list;
    if(bullet_count == 0 ){return list;}

    qreal width = bulletInfo.pixmap.width();
    qreal total_width =width * bullet_count;
    qreal start = bulletX() - total_width/2;
    for(uint8_t i=0; i<bullet_count; i++){
        auto *bullet = new Bullet(bulletInfo);
        bullet->setPos(QPointF(start + width * (i),bulletY()));
        bullet->setView(getView());
        list.append(bullet);
    }
    return list;
}

void Plane::setCount(uint8_t new_count) {
    bullet_count = new_count;
}

void Plane::update(qreal interval_ms) {
    GameItem::update(interval_ms);
    shoot_interval_count += interval_ms;
    if(shoot_interval_count > bulletInfo.interval){
        shoot_interval_count -= bulletInfo.interval;
        shoot();
    }
}
qreal Plane::bulletX() {
    return getPos().x() + getBoundingSize().width()/2;
}
qreal Plane::bulletY() {
    return getPos().y();
}

int Plane::getHp() const {
    return hp;
}
void Plane::setBullet(BulletInfo new_bulletInfo) {
    bulletInfo = std::move(new_bulletInfo);
}
qreal Plane::getMaxSpeed() const {
    return max_speed;
}
int Plane::getBulletCount() const {
    return bullet_count;
}
void Plane::setBulletCount(int bulletCount) {
    bullet_count = bulletCount;
}
const BulletInfo &Plane::getBulletInfo() const {
    return bulletInfo;
}

Bomb::Bomb(GameView *view) : GamePixmapMovieItem({
                                                         QPixmap("://animate/boom/bomb-1.png"),
                                                         QPixmap("://animate/boom/bomb-2.png"),
                                                         QPixmap("://animate/boom/bomb-3.png"),
                                                         QPixmap("://animate/boom/bomb-4.png"),
                                                         QPixmap("://animate/boom/bomb-5.png"),
                                                         QPixmap("://animate/boom/bomb-6.png"),
                                                         QPixmap("://animate/boom/bomb-7.png"),
                                                         QPixmap()
                                                 },850,view),
                             _explosion(this) {
    _explosion.setSource(QUrl("qrc:/music/bomb.wav"));
    _explosion.setLoopCount(1);
    _explosion.setVolume(1);
}
void Bomb::start() {
    GamePixmapMovieItem::start();
    _explosion.play();
}

void HeroPlane::shoot() {
    QList<Bullet *> bullets = GenerateBullet();
    for(auto &&bullet: bullets){
        getView()->addItem(bullet);
        getView()->addHeroBullet(bullet);
    }
}
HeroPlane::HeroPlane(const PlaneInfo &info, GameView *pView) : Plane(info, pView) {
    setBullet(BulletFactor::getHeroBullet(info.bullet_name));
}

EnemyPlane::EnemyPlane(const PlaneInfo &info, GameView *view) : Plane(info, view) {
    setBullet(BulletFactor::getEnemyBullet(info.bullet_name));
}
qreal EnemyPlane::bulletY() {
    return getPos().y() + getBoundingSize().height();
}
void EnemyPlane::shoot() {
    QList<Bullet *> bullets = GenerateBullet();
    for(auto &&bullet: bullets){
        getView()->addItem(bullet);
        getView()->addEnemyBullet(bullet);
    }
}

HeroPlane PlaneFactor::getHeroPlane(const QString &name) {
    return HeroPlane(hero[name]);
}
EnemyPlane PlaneFactor::getEnemyPlane(const QString &name) {
    return EnemyPlane(enemy[name]);
}
void PlaneFactor::addHeroPlane(const QString &name, const PlaneInfo& info) {
    hero.insert(name, info);
}
 void PlaneFactor::removeHeroPlane(const QString &name) {
    hero.remove(name);
}
 void PlaneFactor::addEnemyPlane(const QString &name, const PlaneInfo& info) {
     enemy.insert(name, info);
 }
 void PlaneFactor::removeEnemyPlane(const QString &name) {
     enemy.remove(name);
 }
 BulletInfo BulletFactor::getHeroBullet(const QString &name) {
     return hero[name];
 }
 BulletInfo BulletFactor::getEnemyBullet(const QString &name) {
     return enemy[name];
 }
 void BulletFactor::addHeroBullet(const QString &name, const BulletInfo& info) {
     hero.insert(name, info);
 }
 void BulletFactor::removeHeroBullet(const QString &name) {
     hero.remove(name);
 }
 void BulletFactor::addEnemyBullet(const QString &name, const BulletInfo& info) {
     enemy.insert(name, info);
 }
 void BulletFactor::removeEnemyBullet(const QString &name) {
     enemy.remove(name);
 }
